﻿/**
* CRL
*/
 using System;
using System.Net;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.IO;
using System.Configuration;
using System.Net.Sockets;
using CRL.Core.Log;
using CRL.Core.Extension;
using System.Collections.Concurrent;

namespace CRL.Core
{
    /// <summary>
    /// 写日志
    /// 不想自动记录Context信息请调用Log(string message, string typeName, false)
    /// </summary>
	public class EventLog
    {
        static ThreadWork thread;
        static EventLog()
        {
            thread = new ThreadWork();
            thread.Start("eventLog",() =>
            {
                WriteLogFromCache();
                return true;
            }, 0.3);
        }
        /// <summary>
        /// 是否使用上下文信息写日志
        /// </summary>
        public static bool UseContext = true;

        internal static Action<LogItem> __LogCallBack;
        public static void SetLogCallBack(Action<LogItem> logCallBack)
        {
            __LogCallBack = logCallBack;
        }

        //static object lockObj = new object();
        /// <summary>
        /// 检查目录并建立
        /// </summary>
        /// <param name="path"></param>
		public static void CreateFolder(string path)
		{
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
		}
		/// <summary>
        /// 自定义文件名前辍写入日志
		/// </summary>
		/// <param name="message"></param>
		/// <param name="typeName"></param>
		/// <param name="useContext"></param>
		/// <returns></returns>
        public static bool Log(string message, string typeName, bool useContext)
        {
            LogItem logItem = new LogItem();
            logItem.Detail = message;
            return Log(logItem, typeName, useContext);
        }
        public static bool Log(string message, string typeName)
        {
            return Log(message, typeName, true);
        }
        /// <summary>
        /// 指定日志类型名生成日志
        /// </summary>
        /// <param name="logItem"></param>
        /// <param name="typeName"></param>
        /// <returns></returns>
        public static bool Log(LogItem logItem, string typeName)
        {
            return Log(logItem, typeName, true);
        }
        static HttpContext GetHttpContext()
        {
            return null;
            //return CallContext.GetData<HttpContext>("logHttpContext");
        }
        //public static void SetLogHttpContext(HttpContext contenxt)
        //{
        //    CallContext.SetData("logHttpContext", contenxt);
        //}
        /// <summary>
        /// 指定日志类型名生成日志
        /// </summary>
        /// <param name="logItem"></param>
        /// <param name="typeName"></param>
        /// <param name="useContext">是否使用当前上下文信息</param>
        /// <returns></returns>
        public static bool Log(LogItem logItem, string typeName, bool useContext)
        {
            string fileName = DateTime.Now.ToString("yyyy-MM-dd");
            if (!string.IsNullOrEmpty(typeName))
            {
                fileName += "." + typeName;
            }
            var context = GetHttpContext();
            logItem.Time = DateTime.Now;

            if (context != null && UseContext)
            {
                if (useContext)
                {
                    logItem.UserIP = context.UserIP;
                    logItem.RequestUrl = context.RequestUrl;
                    logItem.UserAgent = context.UserAgent;
                    logItem.UrlReferrer = context.UrlReferrer + "";
                    logItem.Method = context.Method;
                }
            }
            var a = WriteLog(GetLogFolder(), logItem, fileName);
            __LogCallBack?.Invoke(logItem);
            return a;
        }
		/// <summary>
		/// 生成日志,默认文件名
		/// </summary>
		/// <param name="message"></param>
		/// <returns></returns>
		public static bool Log(string message)
		{
			return WriteLog(message);
		}
		/// <summary>
		/// 生成日志,文件名以Error开头
		/// </summary>
		/// <param name="message"></param>
		/// <returns></returns>
		public static bool Error(string message)
		{
			return Log(message,"Error");
		}
		/// <summary>
		/// 生成日志,文件名以Info开头
		/// </summary>
		/// <param name="message"></param>
		/// <returns></returns>
		public static bool Info(string message)
		{
			return Log(message, "Info");
		}
		/// <summary>
		/// 生成日志,文件名以Debug开头
		/// </summary>
		/// <param name="message"></param>
		/// <returns></returns>
		public static bool Debug(string message)
		{
			return Log(message, "Debug");
		}
		/// <summary>
		/// 在当前网站目录生成日志
		/// </summary>
        /// <param name="message"></param>
		public static bool WriteLog(string message)
		{
            return Log(message, "");
		}

        static ConcurrentQueue<LogItem> logQueue = new ConcurrentQueue<LogItem>();

        /// <summary>
        /// 指定路径,文件名,写入日志
        /// </summary>
        /// <param name="path"></param>
        /// <param name="logItem"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static bool WriteLog(string path, LogItem logItem, string fileName)//建立日志
        {
            if (!System.IO.Directory.Exists(path))
            {
                CreateFolder(path);
            }
            if (!string.IsNullOrEmpty(logItem.Folder))
            {
                path = Path.Combine(path, logItem.Folder);
                if (!System.IO.Directory.Exists(path))
                {
                    CreateFolder(path);
                }
            }
            //string filePath = "";
            var id = System.Guid.NewGuid().ToString("N");
            //filePath = path + fileName + ".txt";
            var filePath = Path.Combine(path, fileName + ".txt");
            logItem.Path = filePath;
            logItem.Id = id;
            logQueue.Enqueue(logItem);
            return true;
        }
		public static string LastError;
        public static void WriteLogFromCache()
        {
            //累加上次记录的日志
            if (logQueue.Any())
            {
                var list = new List<LogItem>();
                var i = 0;
                while (logQueue.Any() && i < 1000)
                {
                    var a = logQueue.TryDequeue(out var obj);
                    if (a)
                    {
                        list.Add(obj);
                        i += 1;
                    }
                }
                var group = list.GroupBy(b => b?.Path);
                foreach (var g in group)
                {
                    var path = g.Key;
                    try
                    {
                        var lines = g.Select(b => b.ToString()).ToList();
                        lines.Add("");
                        File.AppendAllLines(path, lines);
                    }
                    catch (Exception ero)
                    {
                        LastError = ero.ToString();
                    }
                }
                list = null;
            }

        }
        static string rootPath = null;
		/// <summary>
		/// 获取日志绝对目录
		/// </summary>
		/// <returns></returns>
		public static string GetLogFolder()
		{
            if (rootPath == null)
            {
                //rootPath = System.Web.Hosting.HostingEnvironment.MapPath(@"\log\");
                //if (string.IsNullOrEmpty(rootPath))
                //{
                //    rootPath = AppDomain.CurrentDomain.BaseDirectory + @"\log\";
                //}
                rootPath = Request.RequestHelper.GetFilePath("log/");
                //rootPath += @"\";
                
            }
			return rootPath;
		}
        public static void Stop()
        {
            if (thread != null)
            {
                thread.Stop();
                //thread = null;
            }
        }
	}
}
